#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <pthread.h>
#include <math.h>
#include <sys/time.h>

/* change d size as needed */
int dimension = 1024;
int pCount;	// number of threads
double *A, *B, *C;

void *mult(void *p) {

	// first calculate the bounds for each thread to calculate
	int bndFrom = ceil(((int)p * dimension) / pCount);
	int bndTo = ceil((((int)p + 1) * dimension) / pCount);
	int i, j, k, d = dimension;

	for(i = bndFrom; i < bndTo; i++) {
		for(j = 0; j < d; j++) {
			for(k = 0; k < d; k++) {
				C[d*i+j] += A[d*i+k] * B[d*k+j];
			}
		}
	}


}

int main(int argc, char *argv[])
{
	int d, i, j, k;
	struct timeval begin, end;

	// changed to pCount
	if (argc == 2)
		pCount = atoi(argv[1]);
	else {
		perror("Missing arg 2\n");
		exit(-1);
	}

	printf("Dimension = %d\n", dimension);

	srand(292);
	int runs = 2;
	int r = runs;
	d = dimension;
	for ( ; r>=0; r--) {
		pthread_t* thread;
		thread = (pthread_t*) malloc(pCount * sizeof(pthread_t));
		A = (double*)malloc(d*d*sizeof(double));
		B = (double*)malloc(d*d*sizeof(double));
		C = (double*)malloc(d*d*sizeof(double));

		for(i = 0; i < d; i++) {
			for(j = 0; j < d; j++) {
				A[d*i+j] = (rand()/(RAND_MAX - 1.0));
				B[d*i+j] = (rand()/(RAND_MAX - 1.0));
				C[d*i+j] = 0.0;
			}
		}

		gettimeofday(&begin, NULL);

		//TODO create the threads here
		int o;
		for (o = 1; o < pCount; o++) {
			if (pthread_create(&thread[o], NULL, mult, (void *)o)) {
				perror("Error creating thread");
				free(thread);
				exit(-1);
			}
		}

		// the main process will be thread 0
		mult(0);

		//join the threads
		for (o = 1; o < pCount; o++) 
			pthread_join(thread[o], NULL);

		gettimeofday(&end, NULL);
		printf("[%d/%d] Multiplication loop took %ldus\t\n", (r+1), (runs+1), ((end.tv_sec * 1000000 + end.tv_usec) - (begin.tv_sec * 1000000 + begin.tv_usec)));

		free(A);
		free(B);
		free(C);
		free(thread);
	}
	printf("\n");


	return 0;
}
